package com.hydra.framework.sp;

import android.content.SharedPreferences;
import android.util.Log;
import androidx.annotation.Nullable;
import com.hydra.framework.event.kvo.KvoFieldAnnotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Set;

/**
 * Created by Hydra.
 *
 */
enum SpFieldType {

    BOOLEAN(Boolean.class) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putBoolean(key, (Boolean) value).apply();
        }
    },
    PRIMITIVE_BOOLEAN(Boolean.TYPE) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putBoolean(key, (Boolean) value).apply();
        }
    },
    FLOAT(Float.class) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putFloat(key, (Float) value).apply();
        }
    },
    PRIMITIVE_FLOAT(Float.TYPE) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putFloat(key, (Float) value).apply();
        }
    },
    INT(Integer.class) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putInt(key, (Integer) value).apply();
        }
    },
    PRIMITIVE_INT(Integer.TYPE) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putInt(key, (Integer) value).apply();
        }
    },
    LONG(Long.class) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putLong(key, (Long) value).apply();
        }
    },
    PRIMITIVE_LONG(Long.TYPE) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putLong(key, (Long) value).apply();
        }
    },
    STRING_SET(Set.class) {
        @SuppressWarnings("unchecked")
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            try {
                sp.edit().putStringSet(key, (Set<String>) value).apply();
            } catch (Throwable e) {
                Log.e("SpFieldType", "mSharedPreferences get String Set Error : " + e);
            }
        }
    },
    STRING(String.class) {
        @Override
        public void putObject(SharedPreferences sp, String key, Object value) {
            sp.edit().putString(key, (String) value).apply();
        }
    };

    public abstract void putObject(SharedPreferences sp, String key, Object value);

    public final Class<?> clazz;

    SpFieldType(Class<?> clazz) {
        this.clazz = clazz;
    }

    @Nullable
    public static SpFieldType getSpFieldType(Field field) {
        KvoFieldAnnotation annotation = field.getAnnotation(KvoFieldAnnotation.class);

        if (annotation == null) {
            return null;
        }

        Class<?> cls = field.getType();

        SpFieldType type = allCfs.get(cls);

        if (type == null) {
            Type genericType = field.getGenericType();
            //判断是否泛型 && 是否是Set.class的子类
            if (genericType instanceof ParameterizedType &&
                    Set.class.isAssignableFrom(field.getType())) {
                ParameterizedType pt = (ParameterizedType) genericType;
                if (String.class.isAssignableFrom((Class<?>) (pt.getActualTypeArguments()[0]))) {
                    type = STRING_SET;
                }
            }
        }

        return type;
    }

    private static HashMap<Class<?>, SpFieldType> allCfs = new HashMap<>();

    static {
        for (SpFieldType type : values()) {
            allCfs.put(type.clazz, type);
        }
    }

    public static SpFieldType getSpFieldType(Class<?> claz) {
        return allCfs.get(claz);
    }
}
